// 版权归Go作者所有。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// go:build js 
// +build js 

package testing

import (
	"fmt"
	"io"
	"os"
	"strings"
	"time"
)

// /TODO（@musiol，@odeke em）：当js/wasm获得os.Pipe实现时，将此代码统一回
// example.go。
func runExample(eg InternalExample) (ok bool) {
	if *chatty {
		fmt.Printf("=== RUN   %s\n", eg.Name)
	}

	// 将标准输出捕获到临时文件。我们没有使用
	// os.Pipe，因为js/wasm不支持它。
	stdout := os.Stdout
	f := createTempFile(eg.Name)
	os.Stdout = f
	finished := false
	start := time.Now()

	// 在延迟通话中进行清理，这样我们可以在示例出现恐慌时恢复。
	defer func() {
		timeSpent := time.Since(start)

		// 恢复标准输出，获取输出并删除临时文件。
		os.Stdout = stdout
		var buf strings.Builder
		_, seekErr := f.Seek(0, os.SEEK_SET)
		_, readErr := io.Copy(&buf, f)
		out := buf.String()
		f.Close()
		os.Remove(f.Name())
		if seekErr != nil {
			fmt.Fprintf(os.Stderr, "testing: seek temp file: %v\n", seekErr)
			os.Exit(1)
		}
		if readErr != nil {
			fmt.Fprintf(os.Stderr, "testing: read temp file: %v\n", readErr)
			os.Exit(1)
		}

		err := recover()
		ok = eg.processRunResult(out, timeSpent, finished, err)
	}()

	// 运行示例。
	eg.F()
	finished = true
	return
}

func createTempFile(exampleName string) *os.File {
	for i := 0; ; i++ {
		name := fmt.Sprintf("%s/go-example-stdout-%s-%d.txt", os.TempDir(), exampleName, i)
		f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
		if err != nil {
			if os.IsExist(err) {
				continue
			}
			fmt.Fprintf(os.Stderr, "testing: open temp file: %v\n", err)
			os.Exit(1)
		}
		return f
	}
}
